/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package uk.ac.cranfield.mzqviewer;

import java.io.File;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import uk.ac.liv.jmzqml.model.mzqml.FeatureList;
import uk.ac.liv.jmzqml.model.mzqml.MzQuantML;
import uk.ac.liv.jmzqml.model.mzqml.PeptideConsensusList;
import uk.ac.liv.jmzqml.model.mzqml.QuantLayer;
import uk.ac.liv.jmzqml.xml.io.MzQuantMLUnmarshaller;

/**
 *
 * @author Jun Fan@cranfield
 */
public class MzqViewer {
    private static String baseFilename;
    private static String csvFilename;

    /**
     * @param args the command line arguments
     */
    private static void parseMZQ(String filename,boolean outputInOneFile){
        File file = new File(filename);
        if(!file.exists()){
            System.out.println("Error: the specified file "+file.getAbsolutePath()+" not found");
            System.exit(0);
        }

        int idx = filename.toLowerCase().lastIndexOf(".mzq");
        if(idx<0){
            System.out.println("Warning: the specified file "+file.getAbsolutePath()+" does not have the suffix mzq, which maybe not the mzQuantML file. Will give a go anyway");
        }
        baseFilename = filename.substring(0,idx);
        csvFilename = baseFilename+".csv";
        
        //validation
//        Validator validator = getValidator("mzQuantML_1_0_0-rc2.xsd");
//        boolean validFlag = validate(validator, filename);
//        if(!validFlag){
//            System.out.println("The mzQuantML validation went wrong, program terminated");
//            System.exit(1);
//        }
        //load the mzQuantML file into memory
        MzQuantMLUnmarshaller unmarshaller = new MzQuantMLUnmarshaller(filename);
        MzQuantML mzQuantML = unmarshaller.unmarshall();
        for(QuantLayer ql:mzQuantML.getProteinList().getAssayQuantLayer()){
            convert("ProteinList_"+ql.getId(), ql, outputInOneFile);
        }
        for(PeptideConsensusList pcList:mzQuantML.getPeptideConsensusList()){
            for(QuantLayer ql:pcList.getAssayQuantLayer()){
                convert("PeptideList_"+pcList.getId()+"_"+ql.getId(), ql, outputInOneFile);
            }
        }
        for(FeatureList featureList:mzQuantML.getFeatureList()){
            for(QuantLayer ql:featureList.getMS2AssayQuantLayer()){
                convert("FeatureList_"+featureList.getId()+"_"+ql.getId(), ql, outputInOneFile);
            }
        }
    }
    
    private static void convert(String objName,QuantLayer ql,boolean append){
        DataTable data = new DataTable(objName, ql);
        if (append) {
            data.saveAsCSV(csvFilename, append);
        } else {
            data.saveAsCSV(baseFilename + "_" + objName + ".csv", append);
        }
    }
    
    static private Validator getValidator(String xsdFilename){
        File xsdFile = new File(xsdFilename);
//        System.out.println(xsdFile.getAbsolutePath());
        if (!xsdFile.exists()) {
            System.out.println("ERROR: Can not find the specified xsd file " + xsdFilename + " to validate the Mascot XML file");
            System.exit(1);
        }
        Source schemaFile = new StreamSource(xsdFile);
        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        try {
            Schema schema = factory.newSchema(schemaFile);
            return schema.newValidator();
        } catch (SAXException ex) {
            Logger.getLogger(MzqViewer.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
    
    private static boolean validate(Validator validator, String xmlFile){
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(xmlFile);
            doc.getDocumentElement().normalize();
            validator.validate(new DOMSource(doc));
        } catch (SAXException e) {
            // instance document is invalid!
            System.out.println("\n\nERROR - when validating the file " + xmlFile + "!");
            System.out.println(e.getMessage());
            return false;
        } catch (Exception e) {
            System.out.println("Exception while validating \n" + e);
            return false;
        }
        return true;
    }
    
    public static void main(String[] args) {
        int len = args.length;
        switch (len){
            case 1:
                parseMZQ(args[0], true);
                break;
            case 2:
                String flag = args[1].toLowerCase();
                if(flag.equals("true") || flag.equals("false")){
                    parseMZQ(args[0], Boolean.parseBoolean(args[1]));
                    break;
                }
            default:
                System.out.println("Usage: java -jar mzQuantMLConverter.jar <mzQuantML file> [one file flag]");
                System.out.println("The mzQuantML file is the file which needs to be parsed");
                System.out.println("The one file flag indicates whether to save the result in one big file or in separate files. The value can only be true (default) or false.");
                System.exit(0);
        }
    }
}
